/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dlc.indexado.lectura;

import java.util.regex.*;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import dlc.modelo.Palabra;
import dlc.persistencia.HiloGrabadorArchivos;
import java.util.ArrayList;
import java.util.Arrays;


public class ImprovedListener extends Listener {

    private String palabraCadena = "";
    private HashMap<String, Palabra> vocabulario;
    private HiloGrabadorArchivos hiloGrabador;
    private String[] terminosBasura;
    
    public int getNroPalabras() {
        return vocabulario.size();
    }

    /**
     * DefaultListener guarda el documento sobre el que se trabaja, el nro de 
     * palabras del mismo, un HashMap con las palabras del mismo y un objeto
     * HiloGrabador encargado de persistir el mismo en la DB 
     * @param doc documento a ser procesado
     * @param hiloGrabador objeto encargado de persistir vocuabulario, doc y posteos
     */
    public ImprovedListener(File doc, HiloGrabadorArchivos hiloGrabador) {
        super(doc);
        vocabulario = new HashMap<String, Palabra>();
        this.hiloGrabador = hiloGrabador;
        terminosBasura = "a,ante,bajo,con,de,desde,durante,en,entre,excepto,hacia,hasta,mediante,para,por,salvo,según,sin,sobre,tras,que,quien,como,cuando,donde,porque,cual,si,no,el,lo,la,las,los,ello,ella,le,se,su,mi,tu,en,y,o".split(",");
        Arrays.sort(terminosBasura);
    }

    @Override
    /**
     * Este metodo es llamado por el Reader en cada "iteración" o "llenado de buffer"
     * toma como entrada una linea del documento, luego la separa en palabras 
     * guardandola en una LinkedList. Por cada palabra:
     * Si es nueva cre un objeto Palabra y lo guarda en el HashMap "vocabulario"
     * Si ya está en vocabulario, le suma uno al tf de dicha palabra
     */
    public boolean listo(String documento) {
        String aux = "";
        for(int i = 0; i < documento.length(); i++)
        { 
            char c = reemplazarCaracterAcentuado((documento.charAt(i)+"").toLowerCase().toCharArray()[0]);
            if(esCaracterDeCorte(c) && aux.trim().length() > 2 && !esTerminoBasura(aux))
            {
                Palabra palabra = vocabulario.get(aux);
                if(palabra == null)
                {
                    palabra = crearPalabra(aux);
                    vocabulario.put(aux, palabra);
                }
                else
                    palabra.setOcurrencias(palabra.getOcurrencias()+1);
                aux = "";
            }
            else
                aux+= c;
        }        
        return true;
    }
    
    public char reemplazarCaracterAcentuado(char c)
    { 
        switch(c)
        {
            case 'á': return 'a';
            case 'é': return 'e';
            case 'í': return 'i';
            case 'ó': return 'o';
            case 'ú': return 'u';               
            default: return c;
        }        
    }
    
    public boolean esCaracterDeCorte(char c)
    {
        Pattern patron = Pattern.compile("[a-zA-Z]");
        Matcher coincidencia = patron.matcher(c+"");
        return !coincidencia.matches();        
    }

    @Override
    /**
     *Este método es llamado por el Reader al momento de finalizar la
     *Lectura del archivo correspondiente.
     * Si el hiloGrabador es null lo instancia. Luego llama al metodo startServer
     * sobre el objeto DefaultListener actual.
     */
    public boolean fin() {
        if (hiloGrabador == null) {
            hiloGrabador = new HiloGrabadorArchivos();
        }
        hiloGrabador.startServer(this);
        return true;
    }

    public HashMap<String, Palabra> getVocabulario() {
        return vocabulario;
    }

    public void setVocabulario(HashMap<String, Palabra> vocabulario) {
        this.vocabulario = vocabulario;
    }

    private Palabra crearPalabra(String aux) {
        Palabra entidad = new Palabra(aux);
        entidad.setOcurrencias(1);
        return entidad;
    }

    public boolean esTerminoBasura(String aux) {
        int ubicacion = Arrays.binarySearch(terminosBasura, aux);
        return  ubicacion > 0;        
    }
    
    
}
